const { statSync, mkdirSync } = require('fs');
const { writeFile, readdir, rm } = require('fs/promises');
const { join } = require('path');
const { readJson, diffObject } = require('./util/util');
const { uuid } = require('./util/uuid');
class SuperModel {
    document = {}
    path = ''

    constructor(collection_name) {
        this.collection_name = collection_name
    }
    // save想要更新，只能使用_id
    async save() {
        let _id = this.document._id;
        // 存在_id，表示这是个更新操作
        if (!_id) {
            _id = uuid()
            this.document._id = _id
        }
        await writeFile(join(this.path, `${_id}.json`), JSON.stringify(this.document))
    }
}

const JsModel = {
    absolutePath: '',
    inited: false,
    model(collection_name, schema) {
        const that = this;
        const collection_path = join(that.absolutePath, collection_name)

        class Model extends SuperModel {
            static async findOne(filter) {
                const dir = await readdir(collection_path)
                const set = new Set(Object.keys(schema))
                for (let key of Object.keys(filter)) {
                    // _id 需要排除
                    if (!set.has(key) && key !== '_id') {
                        // 如果过滤器中的key不在文档中，直接返回null
                        return null
                    }
                }
                for (let filename of dir) {
                    const json = await readJson(join(collection_path, filename))
                    if (diffObject(filter, json)) {
                        return json
                    }
                }
                return null;
            }
            static async updateOne(filter, operate) {
                const json = await this.findOne(filter)
                if (json) {
                    const { $set } = operate
                    if ($set) {
                        for (let key in $set) {
                            // 不能修改唯一_id
                            if (key !== '_id') {
                                json[key] = $set[key]
                            }
                        }
                    }
                    await writeFile(join(collection_path, `${json._id}.json`), JSON.stringify(json))
                    return true
                } 
                return false
            }
            static async deleteOne(filter) {
                const json = await this.findOne(filter)
                if (json) {
                    await rm(join(collection_path, `${json._id}.json`))
                    return true
                }
                return false
            }
            /** @override */
            document = {}
            /** @override */
            path = ''

            constructor(doc) {
                super(collection_name)
                this.document = doc 
                this.path = collection_path
            }
        }
        try {
            const stat = statSync(collection_path)
            if (!stat.isDirectory()) {
                throw new Error(`集合 ${collection_name} 不是目录`)    
            }
        } catch(err) {
            mkdirSync((join(collection_path)))
        }

        return Model
    },
    connect(path) {
        this.absolutePath = path
        try {
            const stat = statSync(path)
            if (!stat.isDirectory()) {
                throw new Error(`${path} 不是一个目录`)
            }
            this.inited = true;
        } catch(err) {
            console.log(`${path} 不存在`)
        }
    }
}
module.exports = JsModel